# -*- coding:utf-8 -*-
import datetime
import pandas as pd
import time
from dateutil.parser import parse
from pandas import DataFrame

class DateFormatStr:
    Y_m_d_H_M_S = '%Y-%m-%d %H:%M:%S'
    YmdHMS = '%Y%m%d%H%M%S'
    Y_m_d = '%Y-%m-%d'
    Ymd = '%Y%m%d'


def is_format_dateStr(dateStr, dateFormat=DateFormatStr.Ymd):
    """
    检测日期字符串是否符合给定的格式
    :param dateStr:
    :return:
    """
    # import re
    # result = re.match(r'^\d{4}-\d{1,2}-\d{1,2}', dateStr)
    # return False if result==None else True
    try:
        datetime.datetime.strptime(dateStr, dateFormat)
        return True
    except:
        return False


def change_date_format(dateStr, sourceFormat=DateFormatStr.Ymd, targetFormat=DateFormatStr.Y_m_d):
    if is_format_dateStr(dateStr, dateFormat=sourceFormat):
        date = datetime.datetime.strptime(dateStr, sourceFormat)
        dateStr = date.strftime(format=targetFormat)
        return dateStr
    else:
        return None


# def is_exist_date_By_DateStr(dateStr: str, dateFormat=DateFormatStr.Y_m_d):
#     """
#     查询给定的日期字符串是否存在
#     :param dateStr: 符合dateFormat
#     :return:
#     """
#     dateStr = dateStr if dateStr else get_today_dateStr()
#     if not dateStr and not is_trading_day(dateStr):
#         return False
#     date_p = datetime.datetime.strptime(dateStr, dateFormat)
#     year, month, day = date_p.year, date_p.month, date_p.day
#     current_year = get_current_year()
#     if (year < 1980 or year > current_year):
#         return False
#     month = int(month)
#     if (month < 1 or month > 12):
#         return False
#     day = int(day)
#     if (day < 1 or day > 31):
#         return False
#     current_month = get_current_month()
#     current_day = get_current_day()
#     if (year == current_year and month == current_month and day > current_day):
#         return False
#     if (year == current_year and month > current_month):
#         return False
#     if (month not in month_31days and month != 2 and day > 30):
#         return False
#     if is_leap_year(year):
#         if (month == 2 and day > 28):
#             return False
#     else:
#         if (month == 2 and day > 29):
#             return False
#     return True


def get_date_before_num_days_by_date(num: int, date):
    current_date = date if date else datetime.date.today()
    return current_date - datetime.timedelta(days=num)


def get_dateStr_before_num_days_by_dateStr(num: int, dateStr: str, dateFormat=DateFormatStr.Y_m_d):
    dateStr = dateStr if dateStr else get_today_dateStr(dateFormat=dateFormat)
    dateTime = get_date_from_dateStr(dateStr, dateFormat=dateFormat)  # type:datetime.datetime
    dateTime = get_date_before_num_days_by_date(num, dateTime)
    return dateTime.strftime(dateFormat)


def get_dateStr_from_dateTime(dateTime, dateFormat=DateFormatStr.Y_m_d_H_M_S):
    return datetime.datetime.strftime(dateTime, dateFormat)


def get_date_from_dateStr(dateStr: str):
    return parse(dateStr)


def get_dateStr_from_dateStr(dateStr, format):
    return parse(dateStr).strftime(format)

def is_leap_year(year: int):
    return True if year > 0 and year % 4 == 0 else False


def today():
    day = datetime.datetime.today().date()
    return day


def get_current_year():
    """
    获取当前年份
    :return: int
    """
    year = datetime.datetime.today().year
    return year


def get_current_month():
    month = datetime.datetime.today().month
    return month


def get_current_day():
    """
    获取当前日期
    :return:
    """
    return datetime.datetime.today().day


def get_current_hour():
    return datetime.datetime.today().hour


def get_current_quarter():
    current_month = get_current_month()
    if current_month in [1, 2, 3]:
        return 1
    elif current_month in [4, 5, 6]:
        return 2
    elif current_month in [7, 8, 9]:
        return 3
    elif current_month in [10, 11, 12]:
        return 4


def get_now_str(dataFormat=DateFormatStr.Y_m_d_H_M_S):
    return time.strftime(dataFormat)


def get_today_dateStr(dataFormat=DateFormatStr.Y_m_d):
    return time.strftime(dataFormat)


def today_last_year():
    lasty = datetime.datetime.today().date() + datetime.timedelta(-365)
    return str(lasty)


def get_timestamp_from_date(date: str, type="start"):
    """
    根据日期字符串获取时间戳
    :param date: format：YYYY-MM-DD ,如果是为None或"",则表示为当前日期
    :param type:
        start 为根据指定日期最早时间生成时间戳(也就是指定日期的"00:00:00"的时间)
        end 为根据指定日期最晚时间生成时间戳(也就是指定日期的"23:59:59"的时间)
    :return: float 示例:1512662400.0
    """
    date = str(today()) if date == None or date == "" else date
    date = date + " 00:00:00" if type == "start" else date + " 23:59:59"
    # 转换成时间数组
    timeArray = time.strptime(date, DateFormatStr.Y_m_d_H_M_S)
    # 转换成时间戳
    timestamp = time.mktime(timeArray)
    return timestamp


def get_long_timestamp_from_dateStr(date: str, type="start"):
    """
    根据日期字符串获取时间戳
    :param date: format：YYYY-MM-DD ,如果是为None或"",则表示为当前日期
    :param type:
        start 为根据指定日期最早时间生成时间戳(也就是指定日期的"00:00:00"的时间)
        end 为根据指定日期最晚时间生成时间戳(也就是指定日期的"23:59:59"的时间)
    :return: float 示例:1512662400.0
    """
    date = str(today()) if date == None or date == "" else date
    date = date + " 00:00:00" if type == "start" else date + " 23:59:59"
    # 转换成时间数组
    timeArray = time.strptime(date, DateFormatStr.Y_m_d_H_M_S)
    # 转换成时间戳
    timestamp = time.mktime(timeArray)
    return int(timestamp * 1000)


def get_timeStr_from_timestamp(timestamp: float, pattern: str):
    """
    根据时间戳获取时间字符串,没有考虑时区
    :param timestamp:float 示例:1512662400.0
    :return:str format:YYYY-MM-DD HH:MM:SS
    """
    if (len(int(timestamp)) == 13):
        timestamp = timestamp / 1000
    time = datetime.datetime.fromtimestamp(timestamp)
    # date_str = time.strftime(DateFormatStr.Y_m_d_H_M_S, time)
    return time.strftime(pattern)


def get_dateStr_from_timestamp(timestamp: float, pattern: str):
    """
    根据时间戳获取时间字符串,没有考虑时区
    :param timestamp:float 示例:1512662400.0
    :return:str format:YYYY-MM-DD
    """
    if (len(str(int(timestamp))) == 13):
        timestamp = timestamp / 1000
    time = datetime.datetime.fromtimestamp(timestamp)
    return time.strftime(pattern)


def get_datetime_from_timestamp(timestamp: float):
    if len(str(int(timestamp))) == 13:
        timestamp = timestamp / 1000
    return datetime.datetime.fromtimestamp(timestamp)


def get_month_FirstDay_LastDay(year=None, month=None):
    """
    获取指定月份的开始日期和结束日期
    :param year: 年份，默认是本年，可传int或str类型
    :param month: 月份，默认是本月，可传int或str类型
    :return: firstDay: 当月的第一天，datetime.date类型
              lastDay: 当月的最后一天，datetime.date类型
    """
    year = int(year) if year else get_current_year()
    month = int(month) if month else get_current_month()

    import calendar
    # 获取当月第一天的星期和当月的总天数
    firstDayWeekDay, monthRange = calendar.monthrange(year, month)

    # 获取当月的第一天
    firstDay = datetime.date(year=year, month=month, day=1)
    lastDay = datetime.date(year=year, month=month, day=monthRange)

    return firstDay, lastDay


def get_year_cut_off(year=None, type="start"):
    """
    获取指定年份的开始和结束日期
    :param year:可以是int,str和None类型
    :param type:str 默认为start,为指定年份的开始日期.end为指定年份的结束日期
    :return:str format：YYYY-MM-DD
    """
    year = get_current_year() if year == None or year == 0 or year == "" else year
    if type == "start":
        return str(year) + "-01-01"
    else:
        return str(year) + "-12-31"


def datetime64_to_datetime(dt64):
    return pd.to_datetime(dt64)


def datetime_to_dateStr(date, pattern):
    return date.strftime(pattern)


if __name__ == "__main__":
    print(is_exist_date_By_DateStr('2021-09-03'))
    print(get_dateStr_before_num_days_by_dateStr(num=1, dateStr='2021-09-01'))
